package code.wrtp;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import code.network.AddressUtil;
import code.network.PacketTx;
import code.wrtp.packets.DataPacket;
import code.wrtp.packets.Packet;

public class Sender implements Runnable {

	private Station station;
	private PacketTx packetTransmitter;
	private volatile boolean isRunning;
	private short address;
	private String subNet;
	private Thread senderThread;
	private MessageBroadcaster messageBroadcaster;
	private final Object lockObject;
	private Queue<Packet> packetsForLowLevel;
	private Queue<DataPacket> forwardingData;
	private Queue<DataPacket> nodeData;

	public Sender(Station station) {
		this.station = station;
		this.subNet = station.getSubNet();
		messageBroadcaster = new MessageBroadcaster();
		packetTransmitter = new PacketTx(subNet, station.getPort(),
				station.getAddressUtil());
		lockObject = new Integer(0);
		packetsForLowLevel = new ConcurrentLinkedQueue<Packet>();
		forwardingData = new ConcurrentLinkedQueue<DataPacket>();
		nodeData = new ConcurrentLinkedQueue<DataPacket>();
	}

	public void startSenderThread() {
		isRunning = true;
		messageBroadcaster.start();
		senderThread = new Thread(this);
		senderThread.start();
	}

	public void stopSenderThread() {
		isRunning = true;
		messageBroadcaster.stopBroadcastThread();
		senderThread.interrupt();
	}

	@Override
	public void run() {
		while (isRunning) {
			try {
				/* While there is no packet wait! */
				synchronized (lockObject) {
					while (packetsForLowLevel.isEmpty()
							&& forwardingData.isEmpty() && nodeData.isEmpty()) {
						lockObject.wait();
					}
				}

			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private class MessageBroadcaster extends Thread {

		private volatile boolean isBroadcasting;

		public MessageBroadcaster() {
			super("MessageBroadcaster");
			isBroadcasting = true;
		}

		public void stopBroadcastThread() {
			isBroadcasting = false;
			this.interrupt();
		}

		@Override
		public void run() {

			while (isBroadcasting) {

			}
		}

		private boolean broadcastPacket(Packet packet) {
			return packetTransmitter.transmitPacket(
					Constants.BROADCAST_ADDRESS, packet.toBytes());
		}
	}

	public boolean broadcastPacket(Packet packet) {
		return messageBroadcaster.broadcastPacket(packet);
	}

	public boolean sendPacket(short destineAddress, Packet packet) {
		return packetTransmitter.transmitPacket(address, packet.toBytes());
	}
}